﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using GiMessCommons;

namespace GiMessServer.Net
{
    public class NetClient
    {
        public TcpClient        Client          { get; set; }
        public NetworkStream    NetStream       { get; set; }
        public StreamReader     NetStreamReader { get; set; }
        public StreamWriter     NetStreamWriter { get; set; }
        public AuthInfo         Credidentials   { get; set; } 

        public string           StringBuffer
        {
            get { return stringBuffer; }
            set { stringBuffer = value; }
        }

        //private Encoding decoder;// = NetConsants.StringEncoder;

        private string stringBuffer = "";

        private char[] charBuffer;
        private byte[] byteBuffer;
        private NetMsg nextMsg;
        private string packet;
        private int    tryRecv;

        //public NetClient()
        //{
        //    decoder = NetConsants.StringEncoder;
        //}
        
        public void Init()
        {
            NetStream = Client.GetStream();
            NetStreamReader = new StreamReader(NetStream);
            NetStreamWriter = new StreamWriter(NetStream);

            NetStream.ReadTimeout = 5;
            NetStreamWriter.AutoFlush = false;

            Credidentials = new AuthInfo();
            //Client.SendTimeout = 10;
        }

        public void Receive()
        {
            tryRecv    = Client.Available;
            byteBuffer = new byte[tryRecv];

            NetStream.Read(byteBuffer, 0, tryRecv);

            stringBuffer += Encoding.UTF8.GetString(byteBuffer);
        }

        public bool SendNetMsg(NetMsg msg)
        {
            NetStreamWriter.Write( msg.Header  );
            NetStreamWriter.Write( msg.Version );
            NetStreamWriter.Write( NetUtils.intToString(msg.Service));
            NetStreamWriter.Write( NetUtils.intToString(msg.Length ));
            NetStreamWriter.Write( msg.Data    );
            
            try
            {
                NetStreamWriter.Flush();
                return true;
            }
            catch { return false; }
        }

        public bool SendNetMsg(NetServices service, string data)
        {
            NetMsg msgToSend = new NetMsg(service, data);
            return SendNetMsg(msgToSend);
        }

        /// <summary>
        /// Decodeaza urmatorul mesaj din buffer
        /// </summary>
        /// <returns>Primul mesaj complet din buffer</returns>
        public NetMsg NextMessage()
        {
            nextMsg = new NetMsg(NetServices.Blank);

            packet = stringBuffer;

            if (packet.Length < 16) return null;

            if (packet.Substring(0, 4) != NetConsants.PacketHeader)
            {
                int index = packet.IndexOf(NetConsants.PacketHeader);
                if (index == -1)
                {
                    Loger.LogLine("Message does not have a header, dumping message...", Loger.ServerLogLevel.Verbose);
                    stringBuffer = "";
                    return null;
                }
                packet = packet.Remove(0, index);              
            }

            packet = packet.Remove(0, 4);       //trim protocol GMSG

            nextMsg.Version = packet.Substring(0, 4);
            packet = packet.Remove(0, 4);       //trim version 1000

            nextMsg.Service = stringToNumber(packet.Substring(0, 4));
            packet = packet.Remove(0, 4);       //trim service

            int len = stringToNumber(packet.Substring(0, 4));
            packet = packet.Remove(0, 4);       //trim pkt_len

            if (len > packet.Length)
            {
                Loger.LogLine("Message not complete, need to recive more...", Loger.ServerLogLevel.Verbose);
                return null;
            }

            nextMsg.Data = packet.Substring(0, len);

            stringBuffer = stringBuffer.Remove(0, len + 16);

            return nextMsg;
        }

        public bool IsBufferEmpty()
        {
            return stringBuffer == "";
        }

        private int stringToNumber(string s)
        {
            int ret = 0;
            char[] chrs = s.ToCharArray();
            for (int i = 0; i < chrs.Length; i++)
            {
                ret = ret * 256 + (int)chrs[i];
            }
            return ret;
        }
    }
}


//public void Receive()
//{
//    int xx;
//    byte[] byteBfr;
//    tryRecv = Client.Available;
//    charBuffer = new char[tryRecv];
//    byteBfr = new byte[tryRecv];
//    xx = NetStream.Read(byteBfr, 0, tryRecv);
//    //xx = NetStreamReader.ReadBlock(charBuffer, 0, tryRecv);
//    //xx = NetStreamReader.Read(charBuffer, 0, tryRecv);
//    if (tryRecv > 0)
//    {
//        int x;
//    }
//    StringBuffer += new string(charBuffer);
//}